<script>
import {
  defineComponent,
  getCurrentInstance,
  ref,
  computed,
  watch,
  useSlots,
} from 'vue';
import {
  createNamespace,
  getElementBounding,
  transformSize,
  transformStyleSize,
} from '../utils';
import { useChildren } from './helper';
import { usePageLifecycle } from '../hooks';
import FanIcon from '../icon/icon.vue';

export default defineComponent({
  name: createNamespace('DropdownMenu')[0],
  options: {
    // https://uniapp.dcloud.io/matter.html#mp
    virtualHost: true,
  },
  components: { FanIcon },
  props: {
    customStyle: [Object, String],
    border: Boolean,
    offset: {
      type: Number,
      default: 0,
    },
    zIndex: Number,
    height: [String, Number],
    color: String,
    activeColor: String,
  },
  emits: ['toggle'],
  setup(props, { emit }) {
    const slots = useSlots();
    const _this = getCurrentInstance();
    const innerOffset = ref(0);
    const barStyle = computed(() => {
      const { customStyle, height, color } = props;
      let s = '';
      if (color) s += `color:${color};`;
      if (height) s += `height:${transformSize(height)};`;
      return transformStyleSize(customStyle) + s;
    });
    const containerStyle = computed(() => {
      const { activeColor, zIndex } = props;
      let s = '';
      if (activeColor) s += `--fan-dropdown-active-color:${activeColor};`;
      if (zIndex) s += `--fan-dropdown-menu-zindex:${zIndex};`;
      return s;
    });

    const { children, linkChildren } = useChildren('fanDropdownMenu');
    const opened = computed(() =>
      children.some((item) => item.state?.showWrapper),
    );
    // #ifdef H5
    let bodyOverflow = '';
    // #endif
    watch(opened, (val) => {
      // #ifdef H5
      const bodyStyle = document.body.style;
      if (val) {
        bodyOverflow = bodyStyle.overflow;
        bodyStyle.setProperty('overflow', 'hidden', 'important');
      } else {
        bodyStyle.setProperty('overflow', bodyOverflow);
      }
      // #endif
      emit('toggle', { opened: val });
    });

    linkChildren({ props, offset: innerOffset });
    const { pageScrollTo, onPageScroll } = usePageLifecycle();
    let scrollTop = 0;
    onPageScroll((e) => {
      scrollTop = e.scrollTop;
    });
    const itemClick = async (i) => {
      const item = children[i];
      const _opened = opened.value;
      if (!item.showWrapper && _opened) {
        children.forEach((a) => a.toggle(false));
      }
      const rect = await getElementBounding({
        selector: '.fan-dropdown-menu__bar',
        scope: _this,
      });
      if (props.offset === null) {
        innerOffset.value = rect?.bottom || 0;
      } else {
        pageScrollTo({
          scrollTop: scrollTop + (rect?.top || 0) - props.offset,
          duration: 0,
        });
        innerOffset.value = (props.offset || 0) + (rect?.height || 0);
      }
      item.toggle(undefined, { immediateBg: _opened });
    };
    const emptyFunc = () => null;

    return {
      barStyle,
      containerStyle,
      children,
      opened,
      itemClick,
      emptyFunc,
      slots,
    };
  },
});
</script>

<template>
  <div :style="containerStyle" class="fan-dropdown-menu">
    <div
      v-if="slots.title"
      :style="barStyle"
      class="fan-dropdown-menu__bar"
      :class="{
        'fan-hairline--bottom': border,
        'fan-dropdown-menu__bar--opened': opened,
      }"
      @touchmove.stop.prevent="emptyFunc"
    >
      <slot name="title" />
    </div>

    <div
      v-else
      :style="barStyle"
      class="fan-dropdown-menu__bar"
      :class="{
        'fan-hairline--bottom': border,
        'fan-dropdown-menu__bar--opened': opened,
      }"
      @touchmove.stop.prevent="emptyFunc"
    >
      <div
        v-for="(item, index) in children"
        :key="index"
        class="fan-dropdown-menu__item"
        :class="{
          'fan-dropdown-menu--active': item.active || item.showWrapper,
        }"
        @click="itemClick(index)"
      >
        <div class="fan-ellipsis">{{ item.title }}</div>
        <FanIcon
          v-if="item.theIcon.name"
          :name="item.theIcon.name"
          :size="item.iconSize"
          :color="item.theIcon.color"
          custom-style="margin:1px 0 0 3px;"
        />
      </div>
    </div>

    <slot />
  </div>
</template>

<style lang="less">
.fan-dropdown-menu {
  --fan-dropdown-menu-height: 40px;
  --fan-dropdown-active-color: var(--fan-primary-color);
  --fan-dropdown-menu-zindex: 80;

  font-size: 14px;

  &__bar {
    height: var(--fan-dropdown-menu-height);
    display: flex;
    align-items: center;
    background-color: #fff;
    position: relative;
    z-index: var(--fan-dropdown-menu-zindex);
  }

  &__bar--opened {
    box-shadow: 0 2px 12px rgba(100, 101, 102, 0.12);
  }

  &__item {
    height: 100%;
    flex: 1;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  &--active {
    color: var(--fan-dropdown-active-color);
  }
}
</style>
